package com.gpipe.dirwatcher;

import java.io.File;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import com.gpipe.dbwriter.AbstractSendResultData;
import com.gpipe.dbwriter.LoadDataByDirectory;
import com.gpipe.dbwriter.Mysql;
import com.gpipe.dbwriter.SendResultData;
import com.gpipe.dirwatcherRealtime.Conf;
import com.gpipe.dirwatcherRealtime.ConfOfMysqlModel;
import com.gpipe.dirwatcherRealtime.DirectorySnapshotRealtime;
import com.gpipe.dirwatcherRealtime.InitialMethod;
import com.gpipe.properties.InputProperties;
import com.gpipe.tools.GpipeInit;
import com.gpipe.tools.SignalList;
import com.gpipe.tools.Tools;

import javax.sound.midi.Soundbank;

public class DirectoryWatcher extends AbstractResourceWatcher {
    /**
     * The current map of files and their timestamps (String fileName => Long
     * lastMod)
     */
    private Map currentFiles = new HashMap();

    /**
     * 记录周期的开始时间如0000 代表0点0分
     */
//    private String periodBeginTime = "0000";
    // /**
    // * The basestations and their longtitude latitude (String lac|ci =>
    // * String longtitude|latitude)
    // */
    // private Map basestation = new HashMap();

    /**
     * The directory to watch.
     */
    private String directory;

    /**
     * The map of last recorded files and their timestamps (String fileName =>
     * Long lastMod)
     */
    private Map prevFiles = new HashMap();

    /**
     * Constructor that takes the directory to watch.
     *
     * @param directoryPath   the directory to watch
     * @param intervalSeconds The interval to use when monitoring this directory. I.e., ever
     *                        x seconds, check this directory to see what has changed.
     * @throws IllegalArgumentException if the argument does not map to a valid directory
     */
    public DirectoryWatcher(String directoryPath, int intervalSeconds)
            throws IllegalArgumentException {

        // Get the common thread interval stuff set up.
        super(intervalSeconds, directoryPath + " interval watcher.");


        // Check that it is indeed a directory.
        File theDirectory = new File(directoryPath);

        if (theDirectory != null && !theDirectory.isDirectory()) {

            // This is bad, so let the caller know
            String message = "The path " + directory
                    + " does not represent a valid directory.";
            throw new IllegalArgumentException(message);

        }
        // Else all is well so set this directory and the interval
        this.directory = directoryPath;

        try {
            InputProperties.basestation.putAll(new InitialMethod().getBasestation());
            InputProperties.baseRegion.putAll(new InitialMethod().getBaseRegion());
            InputProperties.inputdataConf.putAll(new InitialMethod().getInputdataConf());
            InputProperties.baseArea.putAll(new InitialMethod().getBaseArea());
//            InitialMethod initialMethod = new InitialMethod();
//            Conf.timePeriod = initialMethod.getTimePeriod();

            if (InputProperties.inputdataConf.get("lac|ci") == null
                    || InputProperties.inputdataConf.get("lac|ci").split("\\|",
                    -1).length != 2
                    || InputProperties.inputdataConf.get("nbr") == null) {
                System.err
                        .println("The settings of lac|ci or lang|la were wrong.");
                System.exit(0);
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

    /**
     * pc_test:2016-07-27 10:03:23:Initialize the basestation file. 2016-07-27
     * 10:03:23:Start to monitor E:\testLog\jw_test_file\realtime 2016-07-27
     * 10:03:56:Start to writedata into mysql 2016-07-27 10:06:48:Finish writing
     * data into mysql
     *
     * @param args
     */
    public static void main(String[] args) {
        // local test
//        args = new String[]{"E:\\testLog\\jw_test_file\\realtime", "4"};
        // local test-批量跑数测试
//        args = new String[]{"E:\\testLog\\jw_test_file\\realtime\\20170701", "900", "-1"};
        // local test-批量测试居住工作人口
//        args = new String[]{"E:\\testLog\\jw_test_file\\realtime\\20170701", "5", "-1","0000"};

        // Monitor c:/temp every 5 seconds
        if (args.length < 2) {
            System.err.println("useage <dirpath> <interval>");
            System.exit(0);
        }
        if (args.length >= 3) {
            //批量跑数需要提供该标志
            Conf.mode = Integer.parseInt(args[2]);
        }
        if (args.length == 4) {
            //批量跑数模式从哪个时间点开始跑如2345
            DirectorySnapshotRealtime.periodBeginTime = args[3];
        }

        System.out.println("**********参数检查**********");
        System.out.println("**********公共参数**********");
        System.out.println("监控目录："+args[0]);
        System.out.println("扫描时间间隔："+args[1]+"秒");
        if(args.length>=3){
            System.out.println("批量跑数标志："+args[2]+"(-1：批量跑数)");
        }
        if(args.length>=4){
            System.out.println("跑数开始时段："+args[3]);
        }
        System.out.println("基站的数据库表名："+Conf.baseTBN);


        System.out.println("**********二期参数**********");
        System.out.println("mysql数据库批量参数："+Conf.batchSize+"条");
        System.out.println("mysql数据清理周期："+Conf.delPeriod+"天");
        System.out.println("集散量的过滤时间间隔："+Conf.amountPeriod+"秒");
        System.out.println("OD的过滤时间间隔："+Conf.ODPeriod+"秒");
        System.out.println("本地中间结果目录："+new Tools().getPath() + File.separator + Conf.midPath);
        System.out.println("清单层中间结果目录："+new Tools().getPath() + File.separator + Conf.midPath + File.separator + Conf.listSumPath );
        System.out.println("OD中间结果目录："+new Tools().getPath() + File.separator + Conf.midPath + File.separator + Conf.ODLPath);




        DirectoryWatcher dw = new DirectoryWatcher(args[0],
                Integer.parseInt(args[1]));
        dw.addListener(new FileListener());
        dw.start();
    }

    /**
     * Start the monitoring of this directory.
     */
    public void start() {

        // Since we're going to start monitoring, we want to take a snapshot of
        // the
        // current directory to we have something to refer to when stuff
        // changes.
        takeSnapshot();

        // And start the thread on the given interval
        super.start();

        // And notify the listeners that monitoring has started
        File theDirectory = new File(directory);
        monitoringStarted(theDirectory);
    }

    /**
     * Stop the monitoring of this directory.
     */
    public void stop() {

        // And start the thread on the given interval
        super.stop();

        // And notify the listeners that monitoring has started
        File theDirectory = new File(directory);
        monitoringStopped(theDirectory);
    }

    //process:初始化“清单汇总层”，程序启动：1、读取清单汇总层数据；2、读取之前的file快照
    private void initListSum() {
        //1、
        if (DirectorySnapshotRealtime.listSumRecords.size() <= 0) {
            Mysql mysql = new Mysql();
            Connection conn = mysql.createConnect();
            try {

//			删除非DirectorySnapshot.nowFileDate的数据
                String delSql = "delete from jw2_list_nbr_group_bts_sum where date<>" + DirectorySnapshot.nowFileDate;
                mysql.deleteMysql(delSql, conn);

                //读取DirectorySnapshot.nowFileDate数据
                String ST = GpipeInit.writeLogs("--------begin to load DirectorySnapshotRealtime.listSumRecords from mysql!-second period--------");
                ResultSet resultSet = mysql.readMysql("select * from jw2_list_nbr_group_bts_sum", conn);

                //此处需要修改，要不然会逻辑错乱，应该对读取的记录按照时间排序，按照lac|ci聚合
                while (resultSet.next()) {
                    SignalList sl = new SignalList(resultSet.getString(ConfOfMysqlModel.listSumModelParas[2]), resultSet.getString(ConfOfMysqlModel.listSumModelParas[3]), resultSet.getString(ConfOfMysqlModel.listSumModelParas[1]), resultSet.getString(ConfOfMysqlModel.listSumModelParas[4]), resultSet.getString(ConfOfMysqlModel.listSumModelParas[5]), resultSet.getString(ConfOfMysqlModel.listSumModelParas[6]));
                    List<SignalList> val = DirectorySnapshotRealtime.listSumRecords.get(resultSet.getString(ConfOfMysqlModel.listSumModelParas[1]));
                    if (val == null) {
                        val = new ArrayList<SignalList>();
                    }
                    val.add(sl);
                    DirectorySnapshotRealtime.listSumRecords.put(resultSet.getString(ConfOfMysqlModel.listSumModelParas[1]), val);
                }
                resultSet.close();
                String ET = GpipeInit.writeLogs("--------load DirectorySnapshotRealtime.listSumRecords from mysql success!-second period--------");
                GpipeInit.writeLogs("--info--:load DirectorySnapshotRealtime.listSumRecords process total time :" + GpipeInit.duration(ST, ET, "yyyy-MM-dd HH:mm:ss") + "s");
            } catch (SQLException e) {
                e.printStackTrace();
            }


            //2、
            try {
                String selectSql = "select * from jw2_list_file_snapshot";
                ResultSet rs = mysql.readMysql(selectSql, conn);
                while (rs.next()) {
                    DirectorySnapshotRealtime.fileSnapshot.put(rs.getString(ConfOfMysqlModel.fileSnapshotModelParas[0]), Long.parseLong(rs.getString(ConfOfMysqlModel.fileSnapshotModelParas[1])));
                }
                rs.close();
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }


        }


    }

    /**
     * Store the file names and the last modified timestamps of all the files
     * and directories that exist in the directory at this moment.
     */
    private void takeSnapshot() {
        // Set the last recorded snap shot to be the current list
        prevFiles.clear();
//        DirectorySnapshotRealtime.fileSnapshot.clear();
//        DirectorySnapshotRealtime.fileSnapshot.putAll(currentFiles);
        prevFiles.putAll(currentFiles);
        // And get a new current state with all the files and directories
        currentFiles.clear();
        File theDirectory = new File(directory);
        String[] files = theDirectory.list();
        if (files != null && files.length > 0) {
            for (String _f : files) {
                if (_f.contains("interface_")) {
                    String _filePath = GpipeInit.changeToDir(directory) + _f;
                    File _file = new File(_filePath);
                    if (_file.isFile()) {
                        currentFiles.put(_file.getAbsolutePath(), new Long(
                                _file.lastModified()));
                    }
                }
                /*
                 * else if(_file.isDirectory()){ getSnapFiles(_filePath); }
				 */
            }
        }
    }

    //从mysql数据库读出
    private Map<String, String> compare2FileList(Map<String, Long> pre, Map<String, Long> now) {
        Map<String, String> result = new HashMap();
        Iterator currentIt = now.keySet().iterator();
//		DirectorySnapshot.files = new HashMap();
        while (currentIt.hasNext()) {

            String fileName = (String) currentIt.next();
            Long lastModified = (Long) now.get(fileName);

            // If this file did not exist before, but it does now, then
            // it's been added
            if (!pre.containsKey(fileName)) {
                result.put(fileName, fileName);
            } else if (pre.containsKey(fileName)) {
                Long prevModified = pre.get(fileName);
                // If this file existed before and has been modified
                if (prevModified.compareTo(lastModified) != 0) {
                    // Need to check if the file are removed and added
                    // during the interval
                    DirectorySnapshot.addFile(fileName);
                }
            }
        }
        return result;
    }


	/*
     * @SuppressWarnings("unchecked") private void getSnapFiles(String
	 * _filePath){ File _directory = new File(_filePath); String[] children =
	 * _directory.list(); if(children!=null&&children.length>0){ for (int i = 0;
	 * i < children.length; i++) { String _fPath =
	 * GpipeInit.changeToDir(_filePath) + children[i]; File _file = new
	 * File(_fPath);; if(_file.isFile()){
	 * currentFiles.put(_file.getAbsolutePath(), new
	 * Long(_file.lastModified())); }else if(_file.isDirectory()){
	 * getSnapFiles(_fPath); } } } }
	 */

    /**
     * Check this directory for any changes and fire the proper events.
     */
    @SuppressWarnings("unchecked")
    protected void doInterval() {
        SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
        DirectorySnapshotRealtime.fileNameSuffix = df.format(new Date());
        //Print all static propertitys
        GpipeInit.writeLogs("----Print all static propertitys----");
        System.out.println("--baseNbrArea:" + DirectorySnapshotRealtime.baseNbrArea.size());
        System.out.println("--interval:" + DirectorySnapshotRealtime.statInterval);
        System.out.println("--longLaArea:" + DirectorySnapshotRealtime.longLaArea.size());
        System.out.println("--midResults:" + DirectorySnapshotRealtime.midResults.size());
        System.out.println("--NbrArea:" + DirectorySnapshotRealtime.NbrArea.size());
        System.out.println("--nbrLongLaRes:" + DirectorySnapshotRealtime.nbrLongLaRes.size());
        System.out.println("--oneHourFiles:" + DirectorySnapshotRealtime.oneHourFiles.size());
        System.out.println("--records:" + DirectorySnapshotRealtime.records.size());
        System.out.println("--results:" + DirectorySnapshotRealtime.results.size());
        System.out.println("--listSumRecords:" + DirectorySnapshotRealtime.listSumRecords.size());
        GpipeInit.writeLogs("--info--:Conf.mode="+Conf.mode);

        // Take a snapshot of the current state of the dir for comparisons
        takeSnapshot();

//		DirectorySnapshotRealtime.oneHourFiles = new HashMap<String, String>();

        //initial
        DirectorySnapshotRealtime.oneHourFiles.clear();
        DirectorySnapshot.files.clear();
        DirectorySnapshotRealtime.records.clear();
        DirectorySnapshotRealtime.results.clear();
        DirectorySnapshotRealtime.midResults.clear();
        DirectorySnapshotRealtime.nbrLongLaRes.clear();


        // The last filename in the currentFiles
        DirectorySnapshot.lastFileName = null;

        //直接给DirectorySnapshot.brokenPointComFiles 赋值一个周期（15分钟）的文件数，来源于currentFiles
        //如果是批量跑数模式，则执行下面逻辑
        DirectorySnapshot.brokenPointComFiles.clear();
        if (Conf.mode == -1) {
            DirectorySnapshotRealtime.periodEndTime = GpipeInit.getIncreTimePeriodOptional(DirectorySnapshotRealtime.periodBeginTime, InputProperties.inputdataConf.get("timePeriod"),"HHmm","HHmm");
            GpipeInit.writeLogs("--info--:批量跑数模式：现在是在跑从 " + DirectorySnapshotRealtime.periodBeginTime + " to " + DirectorySnapshotRealtime.periodEndTime + " 这个周期数据");

//            int hour = cycle.incrementAndGet() - 1;



//            GpipeInit.writeLogs("--info--:批量跑数模式：现在是在跑第" + hour + "个小时的数据");

            DirectorySnapshot.brokenPointComFiles.clear();

            Iterator currentIt = currentFiles.keySet().iterator();
//		DirectorySnapshot.files = new HashMap();
            while (currentIt.hasNext()) {

                String fileName = (String) currentIt.next();
//                Long lastModified = (Long) currentFiles.get(fileName);

                String fileTime = fileName.substring(
                        fileName.indexOf("interface_")
                                + "interface_".length(),
                        fileName.indexOf(".cdr")).substring(8, 12);
                if (Integer.parseInt(fileTime) >= Integer.parseInt(DirectorySnapshotRealtime.periodBeginTime) && Integer.parseInt(fileTime) <= Integer.parseInt(DirectorySnapshotRealtime.periodEndTime)) {
                    DirectorySnapshot.brokenPointComFiles.put(fileName, fileName);
                }else if (Integer.parseInt(fileTime) >= Integer.parseInt(DirectorySnapshotRealtime.periodBeginTime) && DirectorySnapshotRealtime.periodBeginTime.equals("2345")){
                    DirectorySnapshot.brokenPointComFiles.put(fileName, fileName);
                }

            }
//            DirectorySnapshotRealtime.periodBeginTime = DirectorySnapshotRealtime.periodEndTime;

        } else {
            DirectorySnapshot.brokenPointComFiles.putAll(compare2FileList(DirectorySnapshotRealtime.fileSnapshot, currentFiles));
        }


        // Find the last filename in the currentFiles
        Iterator cuIt = null;
        if (Conf.mode == -1) {
            GpipeInit.writeLogs("--test--:brokenPointComFiles.size=" + DirectorySnapshot.brokenPointComFiles.size());
            cuIt = DirectorySnapshot.brokenPointComFiles.keySet().iterator();
        } else {
            GpipeInit.writeLogs("--test--:currentFiles.size=" + currentFiles.size());
            cuIt = currentFiles.keySet().iterator();
        }


        while (cuIt.hasNext()) {
            String fileName = (String) cuIt.next();
            if (DirectorySnapshot.lastFileName == null) {
                DirectorySnapshot.lastFileName = fileName;
            } else {
                DirectorySnapshot.lastFileName = GpipeInit
                        .returnBiggerStr(DirectorySnapshot.lastFileName, fileName);
            }
        }

        GpipeInit.writeLogs("--info--:DirectorySnapshot.lastFileName=" + DirectorySnapshot.lastFileName);

        if (Conf.mode == -1) {
            if (DirectorySnapshot.brokenPointComFiles.size() > 0) {
                DirectorySnapshot.updateNowDateByFN();
//                initListSum();暂时不要
            }

        } else {


            //second period :initial the listSum level data(DirectorySnapshotRealtime.listSumRecords),when start the program.
            DirectorySnapshot.updateNowDateByFN();
//            initListSum();暂时不要
            System.out.println("--NowFileDate:" + DirectorySnapshot.getNowFileDate());
            cuIt.remove();
            GpipeInit.writeLogs("--##--lastFileName:" + DirectorySnapshot.lastFileName);


            // Iterate through the map of current files and compare
            // them for differences etc...
            Iterator currentIt = currentFiles.keySet().iterator();
//		DirectorySnapshot.files = new HashMap();
            while (currentIt.hasNext()) {

                String fileName = (String) currentIt.next();
                Long lastModified = (Long) currentFiles.get(fileName);

                //If this file is between now and one hour before,then
                //it's been added
                try {
                    if (GpipeInit.inOneHour(DirectorySnapshot.lastFileName, fileName)) {
                        DirectorySnapshotRealtime.oneHourFiles.put(fileName, fileName);
                    }
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                // If this file did not exist before, but it does now, then
                // it's been added
                if (!prevFiles.containsKey(fileName)) {
                    DirectorySnapshot.addFile(fileName);
                    resourceAdded(new File(fileName));
                } else if (prevFiles.containsKey(fileName)) {

                    Long prevModified = (Long) prevFiles.get(fileName);

                    // If this file existed before and has been modified
                    if (prevModified.compareTo(lastModified) != 0) {
                        // Need to check if the file are removed and added
                        // during the interval
                        if (!DirectorySnapshot.containsFile(fileName)) {
                            resourceAdded(new File(fileName));
                        } else {
                            resourceChanged(new File(fileName));
                        }
                        DirectorySnapshot.addFile(fileName);
                    }
                }
            }
        }
//		currentIt.remove();

        //The Entrance of 2period:find the new files and
        //begin to duel with them
        if (DirectorySnapshot.files.size() > 0 || DirectorySnapshot.brokenPointComFiles.size() > 0) {

            String ST = GpipeInit.writeLogs("--------Process begin!-second period--------");
            GpipeInit.writeLogs("--info--:DirectorySnapshotRealtime.listSumIncreRecords.size=" + DirectorySnapshotRealtime.listSumIncreRecords.size());
            LoadDataByDirectory loadDataByDirectory = new LoadDataByDirectory();
            loadDataByDirectory.Mysql2period();// zhengrx
            dualSuccessWriteBak();
            DirectorySnapshotRealtime.fileSnapshot.clear();
            DirectorySnapshotRealtime.fileSnapshot.putAll(currentFiles);
            String ET = GpipeInit.writeLogs("--------Process success!-second period--------");
            GpipeInit.writeLogs("--info--:second period process total time :" + GpipeInit.duration(ST, ET, "yyyy-MM-dd HH:mm:ss")+"s");
        }

//        if(DirectorySnapshot.brokenPointComFiles.size()<=0){
            DirectorySnapshotRealtime.periodBeginTime = DirectorySnapshotRealtime.periodEndTime;
//        }

        GpipeInit.writeLogs("--test--:DirectorySnapshotRealtime.periodBeginTime="+DirectorySnapshotRealtime.periodBeginTime);

        String time = null;
        String date = null;
        if(DirectorySnapshot.lastFileName!=null){
            String fileTime = DirectorySnapshot.lastFileName.substring(DirectorySnapshot.lastFileName.indexOf("interface_") + "interface_".length(), DirectorySnapshot.lastFileName.indexOf(".cdr"));
            time = fileTime.substring(8, 12);
            date = fileTime.substring(0, 8);
        }


        if ((Long.parseLong(time) > 2345 && Long.parseLong(time) <= 2359) || DirectorySnapshotRealtime.periodBeginTime.equals("0000")) {
            GpipeInit.writeLogs("--info--:一天的数据跑完,开始清理一天的数据");
            Mysql mysql =new Mysql();
            Connection conn = new Mysql().createConnect();

            String delSql1 = "truncate table jw2_list_nbr_group_bts_sum";
            mysql.deleteMysql(delSql1,conn);

            String delSql2 = "truncate table jw2_app_od_list";
            mysql.deleteMysql(delSql2,conn);

//            Tools tools = new Tools();
//            String filePath = tools.getPath() + File.separator + Conf.shellPath + File.separator + Conf.interfaceShell;
//            String[] paras = new String[]{date};
//            SendResultData srd = new SendResultData();
//            srd.runShell(filePath,paras);
//            try {
//                conn.close();
//            } catch (SQLException e) {
//                e.printStackTrace();
//            }

        }

        //The Entrance:find the new files and
        //begin to duel with them
        if (DirectorySnapshot.files.size() > 0 && Conf.mode != -1) {
            GpipeInit.writeLogs("--------Process begin!-first period--------");
            LoadDataByDirectory loadDataByDirectory = new LoadDataByDirectory();
            loadDataByDirectory.MysqlRealtime();// zhengrx
        }

        // Now we need to iterate through the list of previous files and
        // see if any that existed before don't exist anymore

        Iterator prevIt = prevFiles.keySet().iterator();

        while (prevIt.hasNext()) {

            String fileName = (String) prevIt.next();

            // If this file did exist before, but it does not now, then
            // it's been deleted
            if (!currentFiles.containsKey(fileName)) {
                DirectorySnapshot.removeFile(fileName);
                resourceDeleted(fileName);
            }
        }



    }


    private void dualSuccessWriteBak() {
        //second period : 把currentFiles存入mysql做备份
        Mysql mysql = new Mysql();
        Connection conn = mysql.createConnect();
        String sqlDel = "truncate table jw2_list_file_snapshot";
        mysql.deleteMysql(sqlDel, conn);
        String sql = "INSERT INTO jw2_list_file_snapshot(fileName,timeStamp)VALUES(?,?)";
        List<String[]> in = new ArrayList<String[]>();
        Iterator iter = currentFiles.entrySet().iterator();
        while (iter.hasNext()) {
            Map.Entry<String, String> entry = (Map.Entry) iter.next();
            in.add(new String[]{entry.getKey(), String.valueOf(entry.getValue())});
        }
        mysql.writeMysql(in, sql, conn);
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


}
